package com.softserveinc.fragments;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.view.Menu;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.softserveinc.MovieManagerApplication;
import com.softserveinc.R;
import com.softserveinc.data.MovieDataManager;
import com.softserveinc.data.help.MovieListType;
import com.softserveinc.fragments.adapter.MovieTableAdapter;
import com.softserveinc.fragments.adapter.MovieTableAdapter.MoviePair;
import com.softserveinc.model.Movie;
import com.softserveinc.model.MovieListData;

public class MovieListFragment extends AbstractListFragment implements
		MovieDataManager.MovieListCallBack,
		MovieDataManager.PageableMovieListCallBack {
	protected static final String TAG = MovieListFragment.class.getSimpleName();

	private MovieTableAdapter movieAdapter;

	private OnListItemClickListener clickListener;

	private MovieManagerApplication application;

	private final MovieListType movieListType;

	private View footer;

	private ListView listView;

	private boolean runWithData = false;

	public MovieListFragment(final MovieListType movieListType) {
		this.movieListType = movieListType;
	}

	@Override
	public View onCreateView(final LayoutInflater inflater,
			final ViewGroup container, final Bundle savedInstanceState) {
		super.onCreateView(inflater, container, savedInstanceState);

		View view = inflater.inflate(R.layout.movie_list, container, false);

		listView = (ListView) view.findViewById(R.id.movie_gridview);

		addFooter();

		return view;
	}

	@Override
	public void onActivityCreated(final Bundle savedInstanceState) {

		super.onActivityCreated(savedInstanceState);

		clickListener = (OnListItemClickListener) getActivity();

		if (movieAdapter == null) {
			movieAdapter = new MovieTableAdapter(getActivity(),
					new ArrayList<Movie>(), this, movieListType);

			movieAdapter.setClickListener(clickListener);
		} else if (movieAdapter.size() == MovieDataManager.MAX_MOVIE_LIST_SIZE) {
			hideFooter();
		}

		listView.setAdapter(movieAdapter);

		application = (MovieManagerApplication) getActivity()
				.getApplicationContext();

		setHasOptionsMenu(true);

		Log.e(TAG, "current loading " + movieListType.name());

		if (runWithData) {
			application.getDataManager().manageDataForMovieList(this,
					movieListType);
		}

		addScrollListner();
	}

	private void showFooter() {
		Log.w(TAG, "adding footer for " + movieListType.name());

		if (footer == null) {
			addFooter();
		} else {
			Log.w(TAG, "footer is not null");
			footer.setVisibility(View.VISIBLE);
		}
	}

	private void addFooter() {
		Log.w(TAG, "footer is null");
		footer = View.inflate(getActivity(), R.layout.listview_footer, null);

		listView.addFooterView(footer);
	}

	private void hideFooter() {
		if (footer != null) {
			Log.e(TAG, "hide footer view");
			footer.setVisibility(View.GONE);
		} else {
			Log.w(TAG, "problem when removing footer");
		}
	}

	private void addScrollListner() {
		listView.setOnScrollListener(movieAdapter.getScrollListener());
	}

	@Override
	public void onDestroyView() {
		super.onDestroyView();

		Log.d(TAG, "destroy view for " + movieListType.name());

		application.getDataManager().recycleImages(movieListType);
	}

	@Override
	public void restrictLoading() {
		hideFooter();
	}

	@Override
	public void allowDownloading() {
		showFooter();
	}

	@Override
	public void postExecute(final MovieListData movieData) {
		List<Movie> movies = movieData.getMovies();

		if (movies.size() > 0) {
			movieAdapter.clear();

			movieAdapter.addMovies(movies);
		}

		movieAdapter.notifyDataSetChanged();

		displayPosters();
	}

	@Override
	public void postExecuteLoading(final MovieListData movieData) {
		List<Movie> movies = movieData.getMovies();

		movieAdapter.addMovies(movies);

		movieAdapter.notifyDataSetChanged();

		displayPosters();
	}

	public void displayPosters() {
		if (movieAdapter == null || movieAdapter.isEmpty()) {
			application.getDataManager().manageDataForMovieList(this,
					movieListType);
		}

		movieAdapter.setBusy(false);

		int first = listView.getFirstVisiblePosition();
		int last = listView.getLastVisiblePosition();

		Log.w(TAG, "to update " + first + " and " + last);

		if (last < 0 || first > last) {
			return;
		}

		if (last == movieAdapter.getCount()) {
			last--;
		}

		List<Movie> list = new ArrayList<Movie>();

		for (int i = first; i <= last; i++) {
			if (movieAdapter.isEmpty()) {
				return;
			}

			MoviePair moviePair = movieAdapter.getItem(i);

			Movie movie = moviePair.getLeftMovie();

			if (movie.getPoster() == null || movie.getPoster().isRecycled()) {
				list.add(movie);
			}

			movie = moviePair.getRightMovie();

			if (movie != null
					&& (movie.getPoster() == null || movie.getPoster()
							.isRecycled())) {
				list.add(movie);
			}
		}

		Log.w(TAG, "at time of update");

		application.getDataManager().manageDataForMovieListImages(list,
				movieAdapter);
	}

	public void recyclePosters() {
		Log.w(TAG, "recycling posters");

		for (int i = 0; i < movieAdapter.getCount(); i++) {
			MoviePair moviePair = movieAdapter.getItem(i);

			Movie movie = moviePair.getLeftMovie();

			recyclePoster(movie);

			movie = moviePair.getRightMovie();

			if (movie != null) {
				recyclePoster(movie);
			}
		}

		movieAdapter.notifyDataSetChanged();
	}

	private void recyclePoster(final Movie movie) {
		Bitmap poster = movie.getPoster();

		if (poster != null && !poster.isRecycled()) {
			poster.recycle();
		}
	}

	@Override
	public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
		inflater.inflate(R.menu.main_menu, menu);
	}

	public void setRunWithData(final boolean runWithData) {
		this.runWithData = runWithData;
	}
}
